#include "conversemessagegroup.h"
#include "converseabstractmessage.h"
#include "account/accountmember.h"

#include <QDateTime>
#include <QDebug>


namespace Converse {

MessageGroup::MessageGroup(QObject *parent) :
    AbstractDataItem(parent)
{
}


MessageGroup::MessageGroup(AbstractMessage *message, QObject *parent)
    : AbstractDataItem(parent)
{
    if (message == NULL)
        return;

    insert(message);
    m_messageFinder.insert(message->id(), message);
}


MessageGroup::MessageGroup(const QList<AbstractMessage *> &messageList, QObject *parent)
    : AbstractDataItem(parent)
{
    if (messageList.isEmpty())
        return;

    foreach (AbstractMessage *message, messageList) {
        if (message == NULL)
            continue;

        insert(message);
        m_messageFinder.insert(message->id(), message);
    }
}


MessageGroup::MessageGroup(const QVarLengthArray<AbstractMessage *> &messageArray, QObject *parent)
    : AbstractDataItem(parent)
{
    if (messageArray.isEmpty())
        return;

    foreach (AbstractMessage *message, messageArray) {
        if (message == NULL)
            continue;
        insert(message);
        m_messageFinder.insert(message->id(), message);
    }
}


MessageGroup::~MessageGroup()
{
    m_messageList.clear();
}


AbstractDataItem::Type MessageGroup::type() const
{
    return AbstractDataItem::MessageGroupType;
}


// Insert message by ascending created time;
void MessageGroup::insert(AbstractMessage *message)
{
    if (message == NULL)
        return;

    MessageFinder::Iterator iterator = m_messageFinder.find(message->id());
    if ((iterator != m_messageFinder.end()) && (message->id() != -1))
        return; // The message exist

    int position = m_messageList.size() - 1;
    for(; position >= 0; --position) {
        const AbstractMessage *positionMessage = m_messageList.at(position);
        Q_ASSERT(positionMessage);
        if (message->createdTime() >= positionMessage->createdTime())
            break;
    }
    position++;
    m_messageList.insert(position, message);
    m_messageFinder.insert(message->id(), message);
    emit messageInserted();
    emit dataChanged();
}


void MessageGroup::append(AbstractMessage *message)
{
    if (message == NULL)
        return;

    MessageFinder::Iterator iterator = m_messageFinder.find(message->id());
    if ((iterator != m_messageFinder.end()) && (message->id() != -1))
        return; // The message exist

    m_messageList.append(message);
    m_messageFinder.insert(message->id(), message);
    emit messageAppended();
    emit dataChanged();
}

qint64 MessageGroup::groupId() const
{
    const qint64 createdTime = QDateTime::currentMSecsSinceEpoch() / 1000;

    if (m_messageList.isEmpty())
        return createdTime;

    const AbstractMessage *firstMessage = m_messageList.first();
    Q_ASSERT(firstMessage);

    if (firstMessage->id() == -1)
        return createdTime;

    return firstMessage->id();
}

qint64 MessageGroup::senderId() const
{
    if (m_messageList.isEmpty())
        return -1;

    const AbstractMessage *firstMessage = m_messageList.first();
    Q_ASSERT(firstMessage);
    return firstMessage->senderId();
}


qint64 MessageGroup::receiverId() const
{
    if (m_messageList.isEmpty())
        return -1;

    const AbstractMessage *firstMessage = m_messageList.first();
    Q_ASSERT(firstMessage);
    return firstMessage->receiverId();
}


qint64 MessageGroup::minimumCreatedTime() const
{
    if (m_messageList.isEmpty())
        return -1;

    const AbstractMessage *firstMessage = m_messageList.first();
    Q_ASSERT(firstMessage);
    return firstMessage->createdTime();
}


qint64 MessageGroup::maximumCreatedTime() const
{
    if (m_messageList.isEmpty())
        return -1;

    const AbstractMessage *lastMessage = m_messageList.last();
    Q_ASSERT(lastMessage);
    return lastMessage->createdTime();
}


int MessageGroup::count() const
{
    return m_messageList.count();
}


int MessageGroup::size() const
{
    return m_messageList.size();
}


AbstractMessage *MessageGroup::at(int index) const
{
    if ((index < 0) || (index > count()))
        return NULL;

    return m_messageList.at(index);
}


const QList<QPointer<AbstractMessage> > &MessageGroup::messageList() const
{
    return m_messageList;
}

} // namespace Converse
